
using Microsoft.EntityFrameworkCore;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Domain.Repositories;
using UniversalAdmin.Infrastructure.Data.Contexts;

namespace UniversalAdmin.Infrastructure.Repositories;

public class RoleRepository : Repository<Role>, IRoleRepository
{
    public RoleRepository(ApplicationDbContext context) : base(context)
    {
    }

    public async Task<Role?> GetWithPermissionsAsync(Guid id)
    {
        return await _context.Roles
            .Include(r => r.RolePermissions)
            .ThenInclude(rp => rp.Permission)
            .FirstOrDefaultAsync(r => r.Id == id);
    }

    public async Task<IEnumerable<Permission>> GetPermissionsByRoleAsync(Guid roleId)
    {
        return await _context.RolePermissions
            .Where(rp => rp.RoleId == roleId)
            .Include(rp => rp.Permission)
            .Select(rp => rp.Permission!)
            .Where(p => p.IsEnabled)
            .ToArrayAsync();
    }

    public async Task<bool> HasPermissionAsync(Guid roleId, string resource, string action)
    {
        return await _context.RolePermissions
            .AnyAsync(rp => rp.RoleId == roleId &&
                           rp.Permission != null &&
                           rp.Permission.Resource == resource &&
                           rp.Permission.Action == action &&
                           rp.Permission.IsEnabled);
    }

    public async Task<IEnumerable<Permission>> GetUserPermissionsAsync(Guid userId)
    {
        var permissions = await _context.Users
            .Where(u => u.Id == userId)
            .SelectMany(u => u.Roles)
            .SelectMany(r => r.RolePermissions)
            .Select(rp => rp.Permission)
            .Where(p => p != null && p.IsEnabled)
            .Distinct()
            .ToArrayAsync();

        return permissions.Where(p => p != null)!;
    }

    public async Task<bool> UserHasPermissionAsync(Guid userId, string resource, string action)
    {
        return await _context.Users
            .Where(u => u.Id == userId)
            .SelectMany(u => u.Roles)
            .SelectMany(r => r.RolePermissions)
            .AnyAsync(rp => rp.Permission != null &&
                           rp.Permission.Resource == resource &&
                           rp.Permission.Action == action &&
                           rp.Permission.IsEnabled);
    }

    public async Task AssignPermissionsToRoleAsync(Guid roleId, List<Guid> permissionIds)
    {
        // 验证角色是否存在
        var role = await GetWithPermissionsAsync(roleId);
        if (role == null)
        {
            throw new KeyNotFoundException($"角色id {roleId} 不存在");
        }

        // 验证权限是否存在
        if (permissionIds != null && permissionIds.Any())
        {
            var validPermissionIds = await _context.Permissions
                .Where(p => permissionIds.Contains(p.Id))
                .Select(p => p.Id)
                .ToListAsync();

            if (validPermissionIds.Count != permissionIds.Count)
            {
                throw new KeyNotFoundException("部分权限id不存在");
            }
        }

        // 清除现有权限
        var existingRolePermissions = role.RolePermissions.ToList();
        _context.RolePermissions.RemoveRange(existingRolePermissions);

        // 添加新权限
        if (permissionIds != null && permissionIds.Any())
        {
            var newRolePermissions = permissionIds.Select(permissionId => new RolePermission
            {
                RoleId = roleId,
                PermissionId = permissionId
            });

            await _context.RolePermissions.AddRangeAsync(newRolePermissions);
        }

        await _context.SaveChangesAsync();
    }

    public async Task ClearRolePermissionsAsync(Guid roleId)
    {
        var rolePermissions = await _context.RolePermissions
            .Where(rp => rp.RoleId == roleId)
            .ToListAsync();

        _context.RolePermissions.RemoveRange(rolePermissions);
        await _context.SaveChangesAsync();
    }

    public async Task<List<Role>> GetRolesByUserAsync(Guid userId)
    {
        return await _context.Users
            .Where(u => u.Id == userId)
            .SelectMany(u => u.Roles)
            .ToListAsync();
    }

    public async Task AssignRolesToUserAsync(Guid userId, List<Guid> roleIds)
    {
        // 验证用户是否存在
        var user = await _context.Users
            .Include(u => u.Roles)
            .FirstOrDefaultAsync(u => u.Id == userId);

        if (user == null)
        {
            throw new KeyNotFoundException($"用户id {userId} 不存在");
        }

        // 验证角色是否存在
        if (roleIds != null && roleIds.Any())
        {
            var validRoleIds = await _context.Roles
                .Where(r => roleIds.Contains(r.Id))
                .Select(r => r.Id)
                .ToListAsync();

            if (validRoleIds.Count != roleIds.Count)
            {
                throw new KeyNotFoundException("部分角色id不存在");
            }
        }

        // 清除现有角色
        user.Roles.Clear();

        // 添加新角色
        if (roleIds != null && roleIds.Any())
        {
            var roles = await _context.Roles
                .Where(r => roleIds.Contains(r.Id))
                .ToListAsync();

            foreach (var role in roles)
            {
                user.Roles.Add(role);
            }
        }

        await _context.SaveChangesAsync();
    }
}